import django_filters as filters
from django.utils import timezone
from datetime import timedelta
from django.db.models import Window, F, Max
from itertools import groupby
from operator import attrgetter
from django_filters import DateTimeFromToRangeFilter, DateFromToRangeFilter
from device.models import deviceInfo, channelInfo, temperatureInfo, warningSettingInfo, warningDeviceInfo


class deviceInfoFilter(filters.rest_framework.FilterSet):
    device_id = filters.CharFilter(field_name='id')

    class Meta:
        model = deviceInfo
        fields = '__all__'


class channelInfoFilter(filters.rest_framework.FilterSet):

    device_id = filters.CharFilter(field_name='belong_device__id')

    class Meta:
        model = channelInfo
        fields = '__all__'


class temperatureInfoFilter(filters.rest_framework.FilterSet):
    # order_time = DateTimeFromToRangeFilter()
    this_tongdao = filters.CharFilter(method='this_tongdao_filter', label='通道类型', lookup_expr='icontains')

    def this_tongdao_filter(self, queryset, name, value):
        queryset_last = queryset.filter(belong_channel__id=value).last()
        if queryset_last:
            queryset = queryset.filter(belong_channel__id=value, order_time=queryset_last.order_time).order_by('meter_address')
        else:
            queryset = queryset.none()
        return queryset

    class Meta:
        model = temperatureInfo
        fields = '__all__'


class warningSettingInfoFilter(filters.rest_framework.FilterSet):
    device_id = filters.CharFilter(field_name='belong_channel__belong_device__id')

    class Meta:
        model = warningSettingInfo
        fields = '__all__'


class warningDeviceInfoFilter(filters.rest_framework.FilterSet):
    device_id = filters.CharFilter(field_name='belong_channel__belong_device__id')
    order_time = DateFromToRangeFilter()
    date = filters.CharFilter(method='date_filter', label='时间日期类型', lookup_expr='icontains')
    type = filters.CharFilter(method='type_filter', label='数据类型的筛选', lookup_expr='icontains')
    last = filters.CharFilter(method='last_filter', label='时间日期类型', lookup_expr='icontains')

    def last_filter(self, queryset, name, value):
        now = timezone.now()
        one_minute_ago = now - timedelta(minutes=1)
        queryset = queryset.filter(order_time__gte=one_minute_ago, order_time__lte=now)
        return queryset

    def type_filter(self, queryset, name, value):
        latest_warnings=[]
        # 使用窗口函数获取每个通道最新的告警信息
        latest_warnings_per_channel = (
            queryset.filter(belong_channel__isnull=False)
            .annotate(
                latest_order_time=Window(
                    expression=Max('order_time'),
                    partition_by=[F('belong_channel')]
                )
            )
            .filter(order_time=F('latest_order_time'))
        )
        latest_warnings_temp = [
            next(group) for key, group in groupby(list(latest_warnings_per_channel), key=attrgetter('belong_channel'))
        ]
        latest_warnings = warningDeviceInfo.objects.filter(pk__in=[x.id for x in latest_warnings_temp])
        return latest_warnings

    # 时间日期类型
    def date_filter(self, queryset, name, value):
        date = value.split('-')
        if len(date) == 1:
            return queryset.filter(order_time__year=date[0])
        elif len(date) == 2:
            return queryset.filter(order_time__year=date[0], order_time__month=date[1])
        elif len(date) == 3:
            return queryset.filter(order_time__year=date[0], order_time__month=date[1], order_time__day=date[2])

    class Meta:
        model = warningDeviceInfo
        fields = '__all__'